#include "global.h"

// Syscall function pointer
typedef (*syscaller)();

// Available syscalls
void getProcessID();
void printStatus();
void changeName(char* name);
void goToKernelMode();
void kernelSwitch();
void wait(int* exitValue);
void exit(int exitValue);

// The commands
char		syscallsNames[7][10] = { "pid", "ps", "chname", "kmode", "kswitch",
				"wait", "exit" };
syscaller	syscalls[7] = { getProcessID, printStatus, changeName, goToKernelMode,
				kernelSwitch, wait, exit };

// The handler responsible for calling the right syscall
void syscallHandler(int a)
{
	int segment = running->userStackSegment;
	int offset = running->userStackPointer;
	u16 a = 0, b = 0, c = 0, d = 0;
	
	a = getWord(segment, offset + 26);
	b = getWord(segment, offset + 28);
	c = getWord(segment, offset + 30);
	d = getWord(segment, offset + 32);
	
	if (a < 7)
	{
		syscalls[a](b, c, d);
	}
	else
	{
		printf("Invalid system call!\n");
	}
}

void installInt80()
{
	putWord((int)int80h, 0x0, 320);
	putWord(0x1000, 0x0, 322);
}

void getProcessID()
{
	putWord(running->processID, running->userStackSegment, running->userStackPointer + 16);
}

void printStatus()
{
	int i = 0, j = 0;
	printf("Name           Status   PID   PPID\n");
	printf("----------------------------------\n");
	for (i = 0; i < NUM_PROCS; ++i)
	{
		printf("%s", processes[i].name);
		for (j = strlen(processes[i].name); j < 15; ++j)
			putc(' ');
		switch(processes[i].status)
		{
			case DEAD: printf("DEAD     "); break;
			case FREE: printf("FREE     "); break;
			case READY: printf("READY    "); break;
			case SLEEP: printf("SLEEP    "); break;
			case ZOMBIE: printf("ZOMBIE   "); break;
		}
		if (processes[i].status != FREE)
			printf("%d     %d\n", processes[i].processID, processes[i].parentProcessID);
		else
			printf("%d\n", processes[i].processID);
	}
}

void changeName(char* name)
{
	int i = 0;
	char curChar = '\0';
	do
	{
		curChar = get_byte(running->userStackSegment, name + i);
		running->name[i] = curChar;
		++i;
	} while (curChar != '\0');
}

void goToKernelMode()
{
	processBody();
}

void kernelSwitch()
{
	tswitch();
}

void wait(int* exitValue)
{
	int status;
	kwait(&status);
	putWord(status, running->userStackSegment, running->userStackPointer + 16);
}

void exit(int exitValue)
{
	kexit(exitValue);
}
